import React, { useEffect, useRef, useCallback } from 'react'
import classNames from 'classnames'
import { getRandom } from '../../common/utils'
// 按钮大小
export enum ButtonSize {
  Large = 'lg',
  Small = 'sm'
}
// 按钮形状
export enum ButtonShape {
  Square = 'square',
  Circle = 'circle'
}
// 按钮类型
export enum ButtonType {
  Primary = 'primary',
  Warning = 'warning',
  Info = 'info',
  Success = 'success',
  Danger = 'danger',
  Default = 'default',
  Gradient = 'gradient',
}
export enum ButtonHover {
  Fault = 'fault',
  Frame = 'frame'
}
// 渐变色方向
export enum GradientDirection {
  ToRight = 'to right',
  ToLeft = 'to left',
  ToBottom = 'to bottom',
  ToTop = 'to top',
}
interface Gradient {
  bgColor: string; // 渐变颜色
  direction?: GradientDirection; // 渐变方向
  flow?: Boolean; // 渐变色流动效果
}
// 按钮功能
interface ButtonProps {
  className?: string;
  disabled?: boolean;
  size?: ButtonSize;
  btnHover?: ButtonHover;
  btnType?: ButtonType;
  // 渐变色相关
  gradient?: Gradient;
  btnShape?: ButtonShape;
  clipRandom?: Boolean;
  clipColor?: string;
  borderColor?: string;
  children?: React.ReactNode;
}

// 整合原生按钮所携带的属性
type BaseBTNProp = ButtonProps & React.ButtonHTMLAttributes<HTMLElement>
// Partial全部类型设置为可选
type BTNProps = Partial<BaseBTNProp>
const Button: React.FC<BTNProps> = (props) => {
  const btnRef = useRef<any>()
  const {
    disabled, // 禁用
    size, // 大小
    btnType, // 类型
    btnShape, // 形状
    gradient, // 渐变按钮配置
    btnHover,
    children,
    clipRandom, // 故障风格字体裂变风格随机
    clipColor, // 故障风格字体颜色，最多两种颜色，字符串，空格隔开
    borderColor, // btnHover为frame时设置border颜色
    className, // 用户自定义的类名
    ...restProps
  } = props
  const classes = classNames('btn', className, {
    [`btn-${size}`]: size,
    [`btn-${btnType}`]: btnType,
    [`btn-${btnHover}`]: btnHover,
    [`btn-${btnShape}`]: btnShape,
    'disabled': disabled
  })
  // 随机故障风格动画
  const faultAnimationRandom = useCallback(
    (): string => {
      let str = ''
      let result = ''
      if (clipRandom) {
        for (let i = 0; i <= 10; i++) {
          let key = i * 10 + '%'
          const clipTop = getRandom(2, 8) * 10
          const clipBottom = getRandom(2, 8) * 10
          let trlX = getRandom(0, 3)
          let trlY = getRandom(0, 3)
          str += `${key}{clip-path: inset(${clipTop}% 0% ${clipBottom}% 0%);transform: translate(${trlX % 2 === 0 ? trlX : -trlX}px, ${trlY % 2 === 0 ? trlY : -trlY}px);}`
        }
        result = `@keyframes move { ${str} }`
      } else {
        result = `
        @keyframes move {
  
          0% {
            clip-path: inset(80% 0% 0% 0%);
            transform: translate(0, 0);
          }
        
          10% {
            clip-path: inset(20% 0% 30% 0%);
            transform: translate(2px, 2px);
          }
        
          20% {
            clip-path: inset(10% 0% 40% 0%);
            transform: translate(3px, 2px);
          }
        
          30% {
            clip-path: inset(40% 0% 20% 0%);
            transform: translate(1px, 2px);
          }
        
          40% {
            clip-path: inset(60% 0% 30% 0%);
            transform: translate(-2px, -3px);
          }
        
          50% {
            clip-path: inset(10% 0% 60% 0%);
            transform: translate(-3px, 2px);
          }
        
          60% {
            clip-path: inset(30% 0% 10% 0%);
            transform: translate(4px, 2px);
          }
        
          70% {
            clip-path: inset(40% 0% 60% 0%);
            transform: translate(-4px, -4px);
          }
        
          80% {
            clip-path: inset(20% 0% 60% 0%);
            transform: translate(4px, 1px);
          }
        
          90% {
            clip-path: inset(80% 0% 30% 0%);
            transform: translate(2px, 5px);
          }
        
          100% {
            clip-path: inset(80% 0% 20% 0%);
            transform: translate(0, 0);
          }
        }
        `
      }
      console.log('动画', result);
      return result
    },
    [clipRandom],
  )
  // 设置故障风格随机动画
  const setFaultAnimation = useCallback(
    () => {
      if (btnHover === ButtonHover.Fault) {
        const str = faultAnimationRandom()
        let styleSheets = document.styleSheets
        let styleSheet = Array.from(styleSheets)[0]
        // 将生成的keyframes插入到styleSheets
        styleSheet.insertRule(str, 0)
      }
      return
    },
    [btnHover, faultAnimationRandom]
  )
  // 设置伪元素字体颜色
  const setPElementColor = useCallback(
    (): void => {
      if (btnHover === ButtonHover.Fault) {
        // 设置设置故障风格字体颜色
        let colorArr = clipColor?.split(' ') || [];
        let color1 = '#e4bf11';
        let color2 = '#de1c31';
        if (colorArr?.length > 0) {
          if (colorArr[0]) color1 = colorArr[0];
          if (colorArr[1]) color2 = colorArr[1];
        }
        const btnNative = btnRef.current
        btnNative.style.setProperty('--color1', color1)
        btnNative.style.setProperty('--color2', color2)
      }
      if (btnHover === ButtonHover.Frame) {
        // 设置边框颜色
        let bColor = borderColor
        if (!borderColor) bColor = 'transparent'
        const btnNative = btnRef.current
        btnNative.style.setProperty('--borderColor', bColor)
      }
    },
    [clipColor, borderColor, btnHover],
  )
  const checkBtn = (gradient: any) => {
    if (btnType === ButtonType.Gradient) {
      return (
        <button
          {...restProps}
          className={classes}
          style={
            {
              backgroundImage: `linear-gradient(${gradient.direction || GradientDirection.ToBottom},${gradient.bgColor})`,
              borderImage: `linear-gradient(${gradient.direction || GradientDirection.ToBottom}, ${gradient.bgColor}) 1 10`,
              animation: gradient.flow && 'flow 8s infinite linear',
              backgroundSize: gradient.flow ? '400%' : '100%'
            }
          }
        >{children}
        </button>
      )
    } else if (btnHover === ButtonHover.Fault) {
      // 故障风格按钮
      return (
        <button
          ref={btnRef}
          className={classes}
          data-content={children}
        >{children}
        </button>
      )
    } else {
      return <button ref={btnRef} className={classes}>{children}</button>
    }
  }

  useEffect(() => {
    setFaultAnimation()
    setPElementColor()
  }, [setFaultAnimation, setPElementColor])
  return (
    checkBtn(gradient)
  )
}
// 按钮默认
Button.defaultProps = {
  disabled: false,
  btnType: ButtonType.Default
}
export default Button;

